/*
 * Copyright (c) Jiandong.
 *
 * This source code is licensed under the MIT license found in the
 * LICENSE file in the root directory of this source tree.
 */

import hilog from '@ohos.hilog';
import { NativeModule } from './NativeModule';
import { ModuleHolder } from './ModuleHolder';
import { ReactContext } from './ReactContext';


import HashMap from '@ohos.util.HashMap'
import ArrayList from '@ohos.util.ArrayList'


/** A set of Java APIs to expose to a particular JavaScript instance. */
export class NativeModuleRegistry {
  private static readonly TAG = "NativeModuleRegistry"
  private mReactContext: ReactContext
  private mModules: HashMap<string, ModuleHolder>
  private mUIModule: NativeModule

  public constructor(reactContext: ReactContext, modules: HashMap<string, ModuleHolder>, uiModule: NativeModule) {
    hilog.info(0x0000, NativeModuleRegistry.TAG, 'constructor')
    this.mReactContext = reactContext;
    this.mModules = modules;
    this.mUIModule = uiModule
  }

  /** Private getters for combining NativeModuleRegistrys */
  private getModuleMap():HashMap<string, ModuleHolder>  {
    return this.mModules;
  }

  private getReactContext(): ReactContext {
    return this.mReactContext;
  }

//  /* package */ HashSet<JavaModuleWrapper> getJavaModules(JSInstance jsInstance) {
//    ArrayList<JavaModuleWrapper> javaModules = new ArrayList<>();
//    for (Map.Entry<String, ModuleHolder> entry : mModules.entrySet()) {
//      if (!entry.getValue().isCxxModule()) {
//        if (ReactFeatureFlags.warnOnLegacyNativeModuleSystemUse) {
//          ReactSoftExceptionLogger.logSoftException(
//              TAG,
//              new ReactNoCrashSoftException(
//                  "Registering legacy NativeModule: Java NativeModule (name = \""
//                      + entry.getValue().getName()
//                      + "\", className = "
//                      + entry.getValue().getClassName()
//                      + ")."));
//        }
//
//        javaModules.add(new JavaModuleWrapper(jsInstance, entry.getValue()));
//      }
//    }
//    return javaModules;
//  }
//
//  /* package */ Collection<ModuleHolder> getCxxModules() {
//    ArrayList<ModuleHolder> cxxModules = new ArrayList<>();
//    for (Map.Entry<String, ModuleHolder> entry : mModules.entrySet()) {
//      if (entry.getValue().isCxxModule()) {
//        if (ReactFeatureFlags.warnOnLegacyNativeModuleSystemUse) {
//          ReactSoftExceptionLogger.logSoftException(
//              TAG,
//              new ReactNoCrashSoftException(
//                  "Registering legacy NativeModule: Cxx NativeModule (name = \""
//                      + entry.getValue().getName()
//                      + "\", className = "
//                      + entry.getValue().getClassName()
//                      + ")."));
//        }
//        cxxModules.add(entry.getValue());
//      }
//    }
//    return cxxModules;
//  }

  /*
   * Adds any new modules to the current module registry
   */
  /* package */ registerModules(newRegister: NativeModuleRegistry) {

//    Assertions.assertCondition(
//        mReactApplicationContext.equals(newRegister.getReactApplicationContext()),
//        "Extending native modules with non-matching application contexts.");

    let newModules = newRegister.getModuleMap();

    for (let item  of  newModules) {
      if (!this.mModules.hasKey(item[0])) {
        this.mModules.set(item[0], item[1]);
      }
    }
  }

//  /* package */ void notifyJSInstanceDestroy() {
//    mReactApplicationContext.assertOnNativeModulesQueueThread();
//    Systrace.beginSection(
//        Systrace.TRACE_TAG_REACT_JAVA_BRIDGE, "NativeModuleRegistry_notifyJSInstanceDestroy");
//    try {
//      for (ModuleHolder module : mModules.values()) {
//        module.destroy();
//      }
//    } finally {
//      Systrace.endSection(Systrace.TRACE_TAG_REACT_JAVA_BRIDGE);
//    }
//  }
//
//  /* package */ void notifyJSInstanceInitialized() {
//    mReactApplicationContext.assertOnNativeModulesQueueThread(
//        "From version React Native v0.44, "
//            + "native modules are explicitly not initialized on the UI thread.");
//    ReactMarker.logMarker(ReactMarkerConstants.NATIVE_MODULE_INITIALIZE_START);
//    Systrace.beginSection(
//        Systrace.TRACE_TAG_REACT_JAVA_BRIDGE, "NativeModuleRegistry_notifyJSInstanceInitialized");
//    try {
//      for (ModuleHolder module : mModules.values()) {
//        module.markInitializable();
//      }
//    } finally {
//      Systrace.endSection(Systrace.TRACE_TAG_REACT_JAVA_BRIDGE);
//      ReactMarker.logMarker(ReactMarkerConstants.NATIVE_MODULE_INITIALIZE_END);
//    }
//  }
//
  public onBatchComplete() {
    // The only native module that uses the onBatchComplete is the UI Manager. Hence, instead of
    // iterating over all the modules for find this one instance, and then calling it, we
    // short-circuit
    // the search, and simply call OnBatchComplete on the UI Manager.
    // With Fabric, UIManager would no longer be a NativeModule, so this call would simply go away
    let moduleHolder: ModuleHolder = this.mModules.get("UIManager");
//    if (moduleHolder != null && moduleHolder.hasInstance()) {
//      ((OnBatchCompleteListener) moduleHolder.getModule()).onBatchComplete();
//    }
  }

//  public <T extends NativeModule> boolean hasModule(Class<T> moduleInterface) {
//    String name = moduleInterface.getAnnotation(ReactModule.class).name();
//    return mModules.containsKey(name);
//  }
//
//  public <T extends NativeModule> T getModule(Class<T extends NativeModule> moduleInterface) {
//    ReactModule annotation = moduleInterface.getAnnotation(ReactModule.class);
//    if (annotation == null) {
//      throw new IllegalArgumentException(
//          "Could not find @ReactModule annotation in class " + moduleInterface.getName());
//    }
//    return (T)
//        Assertions.assertNotNull(
//                mModules.get(annotation.name()),
//                annotation.name()
//                    + " could not be found. Is it defined in "
//                    + moduleInterface.getName())
//            .getModule();
//  }

  public hasModule(name: string): boolean {
    if (name == "uiManager") return true;

    return this.mModules.hasKey(name);
  }

  public getModule(name: string): NativeModule {
//    return Assertions.assertNotNull(mModules.get(name), "Could not find module with name " + name)
//        .getModule();
//
    hilog.info(0x0000, NativeModuleRegistry.TAG, 'getModule %{public}s 222222', name)
    if (name == "uiManager") return this.mUIModule
    hilog.info(0x0000, NativeModuleRegistry.TAG, 'getModule %{public}s 22222', name)
    return this.mModules.get(name).getModule()

  }

  public  getAllModules(): ArrayList<NativeModule> {
    let modules = new ArrayList<NativeModule>();
    for (let item  of this.mModules) {
      modules.add(item[1].getModule());
    }

    return modules;
  }




}
